﻿using System;
using System.ServiceProcess;
using System.Windows.Forms;
using BneyBaruch.Ingest.Core.ServiceProcess;
using BneyBaruch.Ingest.Core.ServiceModel;
using BneyBaruch.Ingest.MorningLesson.Contracts.Interfaces;
using System.ServiceModel;
using BneyBaruch.Ingest.MorningLesson.Contracts.Messages;
using BneyBaruch.Ingest.MorningLesson.WorkflowManagerServices;

namespace BneyBaruch.Ingest.WorkflowManagementMonitor
{
    public partial class frmMonitor : Form
    {
        #region Constants

        private const string ServiceName = "Ingest Workflow Management Service";
        private const string MorningLessonWorkflowProcessorServerEndpointConfigurationName = "MorningLessonWorkflowProcessorServerEndpoint";

        #endregion

        #region Fields

        private readonly ServiceStateWatcher serviceStatusWatcher = new ServiceStateWatcher(ServiceName);
        private MorningLessonWorkflowManager morningLessonWorkflowManager;
        private ServiceHost morningLessonWorkflowManagerServiceHost;
        private MorningLessonWorkflowProcessorCallback morningLessonWorkflowProcessorCallback;

        #endregion

        #region Constructors

        public frmMonitor()
        {
            InitializeComponent();
        }

        #endregion

        #region Services Hosts Manipulation Methods

        private void StopServicesHosts()
        {
            if (morningLessonWorkflowManagerServiceHost.State == CommunicationState.Opened)
                morningLessonWorkflowManagerServiceHost.Close();
        }

        private void StartServicesHosts()
        {
            morningLessonWorkflowProcessorCallback = new MorningLessonWorkflowProcessorCallback(this);
            morningLessonWorkflowManager = new MorningLessonWorkflowManager();
            morningLessonWorkflowManagerServiceHost = new ServiceHost(morningLessonWorkflowManager);
            morningLessonWorkflowManagerServiceHost.Open();
        }

        #endregion

        #region Private Helper Methods

        void serviceStatusWatcher_StateChanged(object sender, ServiceStateChangedEvent e)
        {
            UpdateUIAccordingToServiceState(e.State);
        }

        private void UpdateUIAccordingToServiceState(ServiceState state)
        {
            switch (state)
            {
                case ServiceState.Stopped:
                    // May be called from another thread - like asynchronous service state changed event.
                    if (!this.InvokeRequired)
                    {
                        // In this case we call in UI Thread.
                        mnuStartService.Enabled = true;
                        mnuStopService.Enabled = false;
                    }
                    else
                    {
                        // asynchronous service state changed event
                        this.Invoke(
                            new MethodInvoker(
                                delegate()
                                {
                                    mnuStartService.Enabled = true;
                                    mnuStopService.Enabled = false;
                                }
                            ));
                    }
                    break;
                case ServiceState.StartPending:
                    break;
                case ServiceState.StopPending:
                    break;
                case ServiceState.Running:
                    // May be called from another thread - like asynchronous service state changed event.
                    if (!this.InvokeRequired)
                    {
                        // In this case we call in UI Thread.
                        mnuStartService.Enabled = false;
                        mnuStopService.Enabled = true;
                    }
                    else
                    {
                        // asynchronous service state changed event
                        this.Invoke(
                            new MethodInvoker(
                                delegate()
                                {
                                    mnuStartService.Enabled = false;
                                    mnuStopService.Enabled = true;
                                }
                            ));
                    }
                    break;
                case ServiceState.ContinuePending:
                    break;
                case ServiceState.PausePending:
                    break;
                case ServiceState.Paused:
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region Form Event Handlers

        private void frmMonitor_Load(object sender, EventArgs e)
        {
            StartServicesHosts();
            UpdateUIAccordingToServiceState(serviceStatusWatcher.State);
            serviceStatusWatcher.StateChanged += new ServiceStateChangedEventHandler(serviceStatusWatcher_StateChanged);
            Disposed += new EventHandler(frmMonitor_Disposed);
        }

        void frmMonitor_Disposed(object sender, EventArgs e)
        {
            serviceStatusWatcher.Dispose();
            StopServicesHosts();
        }

        #endregion

        #region Menu Clicks

        private void mnuStartService_Click(object sender, EventArgs e)
        {
            using (ServiceController controller = new ServiceController(ServiceName))
            {
                controller.Start();
                controller.Refresh();
                controller.Close();
            }
        }

        private void mnuExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void mnuStopService_Click(object sender, EventArgs e)
        {
            using (ServiceController controller = new ServiceController(ServiceName))
            {
                controller.Stop();
                controller.Refresh();
                controller.Close();
            }
        }

        private void startToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StartWorkflowResponse startWorkflowResponse = new StartWorkflowResponse(Guid.NewGuid());
            Guid workflowId = Guid.NewGuid();
            DuplexServiceProxy<IMorningLessonWorkflowProcessor>.Call(
                proxy =>
                {
                    startWorkflowResponse = proxy.StartWorkflow(new StartWorkflowRequest(workflowId));
                } // Service proxy delegate call. 
                ,
                new InstanceContext(morningLessonWorkflowProcessorCallback)
                ,
                MorningLessonWorkflowProcessorServerEndpointConfigurationName // Endpoint configuration name
            );
        }

        #endregion
    }
}
